import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
} from "@nestjs/common";
import { Request } from "express";
import { Observable } from "rxjs";
import { CompanyService } from "src/modules/company/company.service";
import { UserService } from "src/modules/user/user.service";
import { JwtPayload } from "src/utils/interfaces/jwt.interface";
import { LogService } from "./log.service";

@Injectable()
export class LogInterceptor implements NestInterceptor {
  constructor(
    private readonly logService: LogService,
    private readonly companyService: CompanyService,
    private readonly usersService: UserService
  ) {}
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request: Request = context.switchToHttp().getRequest();
    const user: JwtPayload = request.user;
    const targetId: string = request.params.id ?? "";
    const method = request.method;
    const controllerMap = new Map<
      string,
      | "Bank"
      | "Client"
      | "Delivery"
      | "Order"
      | "Quality"
      | "Type"
      | "User"
      | "Company"
    >([
      ["BankController", "Bank"],
      ["ClientController", "Client"],
      ["DeliveryController", "Delivery"],
      ["OrderController", "Order"],
      ["QualityController", "Quality"],
      ["TypeController", "Type"],
      ["UserController", "User"],
      ["DeliverOrderController", "Delivery"],
      ["CompanyController", "Company"],
    ]);
    if (
      user &&
      user.company &&
      (method === "POST" || method === "PUT" || method === "DELETE")
    ) {
      const companyId = user.company;
      const userId = user.sub;
      const controllerName = context.getClass().name;
      const type = controllerMap.get(controllerName);
      Promise.all([
        this.companyService.find(companyId),
        this.usersService.find(userId),
      ]).then(([company, user]) => {
        this.logService.create({
          company,
          user,
          type,
          targetId,
          method,
        });
      });
    }

    return next.handle();
  }
}
